//==============================================================================================================================================================
// Author(s): Roman Khmelichek Wei Jiang
//
//==============================================================================================================================================================

#ifndef QUERY_PROCESSOR_H_
#define QUERY_PROCESSOR_H_

// Enables debugging output for this module.
#define QUERY_PROCESSOR_DEBUG

// Enables debugging output for various query algorithms.
#define MAX_SCORE_DEBUG
#define WAND_DEBUG

// Controls some settings for the ProcessLayeredTaatPrunedEarlyTerminatedQuery() algorithm.
#define CUSTOM_HASH           // Our custom hash table performs slightly better than the C++0x one.
#define HASH_HEAP_METHOD_OR   // Enable for much improved performance.
#define HASH_HEAP_METHOD_AND  // Enable for much improved performance.

#include <cassert>
#include <stdint.h>
#include <stdlib.h>
#include <fstream>
#include <iostream>
#include <queue>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <boost/thread.hpp>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include "boost/tuple/tuple.hpp"


//#include <pthread.h>


#include "index_layout_parameters.h"
#include "index_reader.h"
#include "index_util.h"
#include "tcp_connection.h"

#ifdef CUSTOM_HASH
#include "integer_hash_table.h"
#else
#include <tr1/unordered_set>
#endif

using namespace std;
using boost::asio::ip::tcp;

class CacheManager;
class ExternalIndexReader;
struct Accumulator;

typedef struct SCORES_SET {
	float totalScore;

	int doc_length;

	// These set of variables are used for storing the 3 factor probabilities for the specific posting
	double postingThreeFactorProbabilities0;
	double postingThreeFactorProbabilities1;
	double postingThreeFactorProbabilities2;
	double postingThreeFactorProbabilities3;
	double postingThreeFactorProbabilities4;
	double postingThreeFactorProbabilities5;
	double postingThreeFactorProbabilities6;
	double postingThreeFactorProbabilities7;
	double postingThreeFactorProbabilities8;
	double postingThreeFactorProbabilities9;

	// feature updated by Wei 2013/07/13 : BM25 component part1
	float posting0ScoreComponentPart1;
	float posting1ScoreComponentPart1;
	float posting2ScoreComponentPart1;
	float posting3ScoreComponentPart1;
	float posting4ScoreComponentPart1;
	float posting5ScoreComponentPart1;
	float posting6ScoreComponentPart1;
	float posting7ScoreComponentPart1;
	float posting8ScoreComponentPart1;
	float posting9ScoreComponentPart1;

	// feature updated by Wei 2013/07/13 : BM25 component part2
	float posting0ScoreComponentPart2;
	float posting1ScoreComponentPart2;
	float posting2ScoreComponentPart2;
	float posting3ScoreComponentPart2;
	float posting4ScoreComponentPart2;
	float posting5ScoreComponentPart2;
	float posting6ScoreComponentPart2;
	float posting7ScoreComponentPart2;
	float posting8ScoreComponentPart2;
	float posting9ScoreComponentPart2;

	float postingScore0;
	float postingScore1;
	float postingScore2;
	float postingScore3;
	float postingScore4;
	float postingScore5;
	float postingScore6;
	float postingScore7;
	float postingScore8;
	float postingScore9;

	long postingTermFrequency0;
	long postingTermFrequency1;
	long postingTermFrequency2;
	long postingTermFrequency3;
	long postingTermFrequency4;
	long postingTermFrequency5;
	long postingTermFrequency6;
	long postingTermFrequency7;
	long postingTermFrequency8;
	long postingTermFrequency9;

	long lengthOfTheInvertedList0;
	long lengthOfTheInvertedList1;
	long lengthOfTheInvertedList2;
	long lengthOfTheInvertedList3;
	long lengthOfTheInvertedList4;
	long lengthOfTheInvertedList5;
	long lengthOfTheInvertedList6;
	long lengthOfTheInvertedList7;
	long lengthOfTheInvertedList8;
	long lengthOfTheInvertedList9;

} SCORES_SET;

typedef std::pair<float, uint32_t> Result;

typedef std::pair<SCORES_SET, uint32_t> Result_Wei_2012;

typedef std::pair<string, string> SocketAddr;

typedef struct QUERY_RESULT {
	double score;
	unsigned long docId;
	const char* url;
} QUERY_RESULT;

typedef struct POSTING_RESULT{
	const char* queryTerm;
	unsigned int queryTermLength;
	unsigned int queryTermID;
	unsigned long docId;
	double score;
} POSTING_RESULT;

/**************************************************************************************************************************************************************
 * Class QueryProcessor
 *
 * Implements various query algorithms. These support block caching (for on-disk indices) and chunk skipping. Frequencies and positions (if used) are
 * only decoded if the algorithm needs to score a docID.
 **************************************************************************************************************************************************************/
class LocalQueryProcessor {
public:
#ifdef CUSTOM_HASH
  // The OpenAddressedIntegerHashTable performs slightly better than the ChainedIntegerHashTable for top-k, tested at k = 10 and k = 1000.
  typedef OpenAddressedIntegerHashTable TopKTable;
  /*typedef ChainedIntegerHashTable TopKTable;*/
#else
  typedef std::tr1::unordered_set<uint32_t> TopKTable;
#endif

  enum QueryAlgorithm {
    kDefault,  // The query algorithm to use will be the default one used for the type of index that's being queried.
    kDaatAnd,  // Standard DAAT processing with AND mode semantics.
    kDaatOr,   // Standard DAAT processing with OR mode semantics.
    kTaatOr,   // Standard TAAT processing with OR mode semantics.

    // DAAT processing with an overlapping layered index, with a maximum of two layers per list. AND mode semantics.
    // These algorithms are early terminating only if certain conditions are met, otherwise,
    // queries are rerun with standard DAAT processing on the last layers of the lists.
    kDualLayeredOverlappingDaat,       // Each first layer is intersected with the other second layers. The results are then merged.
    kDualLayeredOverlappingMergeDaat,  // The first layers are merged into a single list and this list is then intersected with all the second layers.

    kLayeredTaatOrEarlyTerminated,  // TAAT processing on a multiple layered, but not overlapping index. Early termination possible. Also has accumulator trimming.
    kMultiLayeredDaatOr,
    kMultiLayeredDaatOrMaxScore,

    kWand,
    kDualLayeredWand,

    kMaxScore,
    kDualLayeredMaxScore,

    kDaatAndTopPositions
  };

  // For AND semantics, all query terms must exist in the lexicon for query processing to proceed.
  // For OR semantics, any of the query terms can be in the lexicon.
  enum ProcessingSemantics {
	kAnd, kOr, kUndefined
  };

  enum QueryMode {
    kInteractive, kInteractiveSingle, kBatch, kBatchBench, kGetPostingRankInListBatch, kGetPostingRankInListInteractive,kGetPostingRankInListInteractiveSingle, kSpecialBM25wsep, kSpecialPurpose1, kQueryView
  };

  enum ResultFormat {
    kTrec, kNormal, kCompare, kDiscard,kPruning
  };

  // Updated by Wei 2013/09/11 afternoon at school
  // currently in use and still keep to date
  LocalQueryProcessor(const IndexFiles& input_index_files, const char* stop_words_list_filename, QueryAlgorithm query_algorithm, QueryMode query_mode,
                 ResultFormat result_format, map<string,float> queryTermsProbabilityDistributionMap);

  // Updated by Wei 2013/08/12 night at school
  // This constructor is rarely used and out of date for months
  LocalQueryProcessor(const IndexFiles& input_index_files, const char* stop_words_list_filename, QueryAlgorithm query_algorithm, QueryMode query_mode,
                 ResultFormat result_format, string operation_mode);

  void LoadUpQueryTermsProbabilityDistribution_Advance();

  void GetOverallQueryProcessingStatistics();

  ~LocalQueryProcessor();

  void LoadStopWordsList(const char* stop_words_list_filename);

  void LoadQueryView();

  void LoadQueryTermThresholdsKeptBasedOnPercentage();

  void BuildBlockLevelIndex();

  void AcceptQuery();
  void AcceptRequest();




  void OpenListLayers(LexiconData** query_term_data, int num_query_terms, int max_layers, ListData* list_data_pointers[][MAX_LIST_LAYERS],
                      bool* single_term_query, int* single_layer_list_idx, int* total_num_layers);

  void CloseListLayers(int num_query_terms, int max_layers, ListData* list_data_pointers[][MAX_LIST_LAYERS]);

  int ComputeBM25ScoreForSpecifcTerm(LexiconData** query_term_data, int num_query_terms, Result* results, int* num_results, string term);

  int CombineBM25ScoreIntoExistingTermFeatureFile();

  int assignBM25ScoreToTermFeatureFile(map<string, double> &lookUpDictForBM25Score);

  int ProcessModifyInvertedIndexesPreComputedScores(LexiconData** query_term_data, int num_query_terms, string mode);
  int ProcessUpdateInvertedIndexesPreComputedScores(LexiconData** query_term_data, string query_term, uint32_t doc_id, float new_score);

  int ProcessQuery(LexiconData** query_term_data, int num_query_terms, Result* results, int* num_results);
  int ProcessQuery2(LexiconData** query_term_data, int num_query_terms, Result_Wei_2012* results, int* num_results);

  // Updated by Wei on 2013/09/11 afternoon at school
  int GetPostingRankInList(LexiconData** term_data,string term,uint32_t docID);

  int ProcessMultiLayeredDaatOrQuery(LexiconData** query_term_data, int num_query_terms, Result* results, int* num_results);
  int ProcessMultiLayeredDaatOrMaxScoreQuery(LexiconData** query_term_data, int num_query_terms, Result* results, int* num_results);

  int ProcessLayeredTaatPrunedEarlyTerminatedQuery(LexiconData** query_term_data, int num_query_terms, Result* results, int* num_results);
  float ProcessListLayerOr(ListData* list, Accumulator** accumulators_array, int* accumulators_array_size, int* num_accumulators,
                           std::pair<uint32_t, float>* top_k, int& num_top_k, TopKTable& top_k_table, int k, int* total_num_accumulators_created);
  float ProcessListLayerAnd(ListData* list, Accumulator* accumulators, int num_accumulators, std::pair<uint32_t, float>* top_k, int& num_top_k,
                            TopKTable& top_k_table, int k);

  int ProcessLayeredQuery(LexiconData** query_term_data, int num_query_terms, Result* results, int* num_results);

  void KthAccumulator(const Accumulator& new_accumulator, std::pair<uint32_t, float>* accumulators, int num_accumulators, TopKTable& top_k_table, int kth_score);
  void BubbleDownHeap(std::pair<uint32_t, float>* top_k, int top_k_size, int node_idx);
  void KthScore(float new_score, float* scores, int num_scores, int kth_score);

  void outputAllDocIDWARCTRECIDPair();
  void ComputeBM25BasedOnCentainList(string flagString);
  void LoadUpBM25TermList(vector<string> &BM25TermList);
  void LoadUpAuxFileForPruningProject();
  void GetPostingRankInListGivenASpecifcPostingIdentifier();
  int ComputeBM25Score(ListData** lists, int num_lists, Result* results, int num_results, string term);
  int ComputeBM25Score(ListData** merge_lists, int num_merge_lists, ListData** lists, int num_lists, Result* results, int num_results, string term);
  void computeBM25ScoreGivenTerm(string query_line, int qid, ofstream &outputFileHandler, map<string, float> &bm25LookUpDict, string flagString);

  int UpdateExternalPreComputedScores(LexiconData** query_term_data, ListData** lists, string query_term, uint32_t doc_id, float new_score);

  int IntersectListsForModifyingPreComputedScores(LexiconData** query_term_data, ListData** merge_lists, int num_merge_lists, ListData** lists, int num_lists, bool debugFlag, string mode,POSTING_RESULT* posting_results); // inside layer of the function
  int IntersectListsForModifyingPreComputedScores(LexiconData** query_term_data, ListData** lists, int num_lists, string mode,POSTING_RESULT* posting_results); // outside layer of the function.
  int IntersectListsEspecaillyForPruningProject(ListData** lists, int num_lists, Result* results, int num_results);
  int IntersectListsEspecaillyForPruningProject2(ListData** lists, int num_lists, Result_Wei_2012* results, int num_results);
  int MergeListsEspeciallyForPruningProject2(ListData** lists, int num_lists, Result_Wei_2012* results, int num_results);

  int IntersectLists(ListData** lists, int num_lists, Result* results, int num_results); // outside layer of the function.
  int IntersectLists(ListData** merge_lists, int num_merge_lists, ListData** lists, int num_lists, Result* results, int num_results, bool pruningProjectSwitch); // inside layer of the function1
  int IntersectLists(ListData** merge_lists, int num_merge_lists, ListData** lists, int num_lists, Result* results, int num_results, bool onComputeFlag, int computeMode); // inside layer of the function2

  int IntersectLists2ScoreComputeOnline(ListData** merge_lists, int num_merge_lists, ListData** lists, int num_lists, Result_Wei_2012* results, int num_results, bool pruningProjectSwitch, bool currentlyNOUsePlaceHolder,int computation_method); // inside layer of the function1
  int IntersectLists2ScoreExtractedFromExternal(ListData** merge_lists, int num_merge_lists, ListData** lists, int num_lists, Result_Wei_2012* results, int num_results, bool debugFlag); // inside layer of the function2

  int IntersectListsTopPositions(ListData** lists, int num_lists, Result* results, int num_results);

  float make_the_value_into_string_format_with_fixed_mode(float originalValue, int precisionNumber, bool debugFlag);

  int MergeLists(ListData** lists, int num_lists, uint32_t* merged_doc_ids, int max_merged_doc_ids);
  int MergeLists(ListData** lists, int num_lists, Result* results, int num_results, bool pruningProjectSwitch);
  int MergeLists2ScoreComputeOnline(ListData** lists, int num_lists, Result_Wei_2012* results, int num_results, bool pruningProjectSwitch, float lowerBoundThreshold, int computation_method);
  int MergeLists2ScoreExtractedFromExternal(ListData** lists, int num_lists, Result_Wei_2012* results, int num_results, bool scoreModificationFlag,int computerMode);
  int MergeListsForModifyingPreComputedScores(LexiconData** query_term_data, ListData** lists, int num_lists, string mode,POSTING_RESULT* posting_results); // outside layer of the function.
  int MergeListsForModifyingPreComputedScores(LexiconData** query_term_data, ListData** lists, int num_lists,bool debugFlag, string mode,POSTING_RESULT* posting_results); // inside layer of the function1(currently, no function2 inside)

  int MergeListsWand(LexiconData** query_term_data, int num_query_terms, Result* results, int* num_results, bool two_tiered);
  int MergeListsMaxScore(LexiconData** query_term_data, int num_query_terms, Result* results, int* num_results, bool two_tiered);

  void ExecuteQuery(std::string query_line, int qid);
  void ExecuteRequest(std::string request_line);

  // Updated on 2013/08/12 night by Wei at school.
  // Note: The following function int ExecuteQuery(...) is currently ONLY being used in the cPythonQueryInterface.cc file
  int ExecuteQuery(string query_line, int qid, vector<string> &resultsInString, int max_num_results_to_return);

  void UpdateInvertedIndexesPreComputedScores(string query_term, uint32_t doc_id, float new_score);
  int ModifyInvertedIndexesPreComputedScores(int qid, std::string query_line, std::string semantics, string mode);

  void RunBatchRequests(const std::string& input_source);
  void RunBatchQueries(const std::string& input_source, bool warmup, int num_timed_runs);
  void RunQueryViewQueries(const std::string& input_source);

  void LoadIndexProperties();

  void PrintQueryingParameters();

  void UpdateExternalIndexFromHardDrive();

  void LoadUpTheCombinationOfSecondANDThirdFactorProbabilityTable();

  void LoadUpAuxFilesForFirstProbabilityFactor();

  void LoadUpAuxFilesForSecondProbabilityFactor();

  void LoadUpThreeFeatureValuesForMachineLearnedTraining();

  float ComputeThirdFactorProbability(int queryTermPostionIndexNum, float valueOfPartialBM25ScoreComponentPart1_IDF,float valueOfPartialBM25ScoreComponentPart2_TF,float postingScore_1, uint32_t termFreqInDoc_4,int doc_words_5, float &probabilityPostingGivenQueryTerms);

  POSTING_RESULT* posting_results_ptr();

private:
  CacheManager* GetCacheManager(const char* index_filename) const;
  const ExternalIndexReader* GetExternalIndexReader(QueryAlgorithm query_algorithm, const char* external_index_filename) const;

  ProcessingSemantics processing_semantics_; // The query processing semantics.
  QueryAlgorithm query_algorithm_;  // The query algorithm to use. This is also dependent on the type of index we're using.
  QueryMode query_mode_;            // The way we'll be accepting queries.
  ResultFormat result_format_;      // The result format we'll be using for the output.

  std::set<std::string> stop_words_;

  int max_num_results_;  // The max number of results to display.
  bool silent_mode_;     // When true, don't produce any output.
  bool warm_up_mode_;    // When true, don't time or count the queries. Queries issued during this time will be used for warming up the cache.
  bool use_positions_;   // Whether positions will be utilized during ranking (requires index built with positions).

  uint32_t collection_average_doc_len_;  // The average document length of a document in the indexed collection.
                                         // This plays a role in the ranking function (for document length normalization).
  uint32_t collection_total_num_docs_;   // The total number of documents in the indexed collection.

  const ExternalIndexReader* external_index_reader_;  // Only used for certain querying algorithms. I know, but I need to know how to use it(wei)

  CacheManager* cache_policy_;

  IndexReader index_reader_;

  // Some additional index information.
  bool index_included_precomputed_score_;
  bool index_use_precomputed_score_;
  bool index_layered_;
  bool index_overlapping_layers_;
  int index_num_layers_;  // This is really the max number of layers, since small inverted lists might have less layers.

  // Query statistics.
  double total_querying_time_;             // Keeps track of the total elapsed query times.
  uint64_t total_num_queries_;             // Keeps track of the number of queries issued.
  uint64_t num_early_terminated_queries_;  // Keeps track of the number of queries which were able to early terminate (when using a layered index).
  uint64_t num_single_term_queries_;       // Keeps track of the number of single term queries issued.

  // Statistics related to various query processing strategies.
  uint64_t not_enough_results_definitely_;
  uint64_t not_enough_results_possibly_;
  uint64_t num_queries_containing_single_layered_terms_;

  uint64_t num_queries_kth_result_meeting_threshold_;
  uint64_t num_queries_kth_result_not_meeting_threshold_;

  uint64_t num_postings_scored_;
  uint64_t num_postings_skipped_;



  map<string, int> termWithTheLengthOfListDict_;
  vector<int> originalListLengthsVectorForPruningProjectForCurrentQueries_;

  typedef std::pair<string, int> queryTermPostionIndexPair;

  vector<queryTermPostionIndexPair> queryTermPostionIndexPairs_;

  // posting results in the array.
  POSTING_RESULT* posting_results_ptr_;

  // the max is set to 200000
  //POSTING_RESULT posting_results[200000];  // Using a variable length array here.

  // Note: Updated by wei 20130619
  // I think this variable queryTermsProbabilityDistributionMap_ has no use at all. But just still leave it here for the legacy code.
  map<string,float> queryTermsTrueProbabilityDistributionMap_;
  map<string,float> queryTerms1DProbabilityDistributionMap_;
  map<string,float> queryTerms2DProbabilityDistributionMap_;
  map<string,float> queryTermsGoodTuringProbabilityDistributionMap_;

  // 3 feature maps
  map<string,float> query_terms_length_of_the_inverted_index_map_;
  map<string,float> query_terms_term_freq_in_collection_map_;
  map<string,float> query_terms_term_freq_in_queries_map_;

  // Updated by Wei 2013/08/31 afternoon at school
  // the simplified version of the 3 factor model
  // the same naming convention like --cat command logic
  // key: class label in int format
  // value: class partial bm25 lower bound in float format
  // This is the variable(1 out of 2) for the naive pruning method based on some partialBM25 ranges
  map<int, float> class_label_with_lower_bounds_map_;

  // key: class label in int format
  // value class probability in float format
  // This is the variable(2 out of 2) for the naive pruning method based on some partialBM25 ranges
  map<int, float> class_label_with_probability_map_;

  // aux maps for the first probability factor
  map<int,float> freq_first_factor_probability_map_;
  map<string,int> terms_with_corresponding_species_belonging_to_map_;

  // aux maps for the second probability factor
  map<int,float> query_length_probability_map_;
  map<string,float> docID_With_Xdoc_Value_goldStandarded_map_;
  map<string,float> docID_With_Xdoc_Value_1D_map_;
  map<string,float> docID_With_Xdoc_Value_2D_map_;
  map<string,float> docID_With_Xdoc_Value_goodTurning_map_;

  // Note: Updated by Wei 20130620
  // The init value should be -1 and this value should be changed according to the irtk.conf file
  int queryTermPredictionModelValue_;

  // add the variables for the universal threshold and the other data structures for storing the thresholds for each term and each document
  double universal_threshold_socre_of_posting_;

  map<string,vector<float> > term_thresholds_based_on_percentage_;
  int indexPositionOfCorrespondingThresholdToUse_;

  // old:
  // 	level1:
  // 		key: term value: docID
  // 	level2:
  // 		key: docID value: numOfTimesThePostingsBegingTouched
  // map<string, map<uint32_t,int> > queryView_;
  // new:
  // 	level1:
  //		key: term value: docID
  //	level2:
  //		key: docID value: rank list
  map<string, map<uint32_t,float> > queryView_;

};

/**************************************************************************************************************************************************************
 * ResultPositionTuple
 *
 **************************************************************************************************************************************************************/
struct ResultPositionTuple {
  uint32_t doc_id;
  int doc_len;
  float score;
  uint32_t* positions;

  // Used to implement min heap for candidate documents.
  bool operator<(const ResultPositionTuple& rhs) const {
    return score > rhs.score;
  }

  // Used to sort documents in descending order by score.
  bool operator()(const ResultPositionTuple& l, const ResultPositionTuple& r) const {
    return l.score > r.score;
  }
};

/**************************************************************************************************************************************************************
 * Accumulator
 *
 **************************************************************************************************************************************************************/
struct Accumulator {
  uint32_t doc_id;
  float curr_score;
  uint32_t term_bitmap;  // Bit is on if the docID belonging to the corresponding term has been accounted for in the current score.

  bool operator<(const Accumulator& rhs) const {
    return doc_id < rhs.doc_id;
  }
};

/**************************************************************************************************************************************************************
 * AccumulatorScoreDescendingCompare
 *
 **************************************************************************************************************************************************************/
struct AccumulatorScoreDescendingCompare {
  bool operator()(const Accumulator& l, const Accumulator& r) const {
    return l.curr_score > r.curr_score;
  }
};

/**************************************************************************************************************************************************************
 * AccumulatorScoreAscendingCompare
 *
 **************************************************************************************************************************************************************/
struct AccumulatorScoreAscendingCompare {
  bool operator()(const Accumulator& l, const Accumulator& r) const {
    return l.curr_score < r.curr_score;
  }
};

/**************************************************************************************************************************************************************
 * DocIdScorePairScoreDescendingCompare
 *
 **************************************************************************************************************************************************************/
struct DocIdScorePairScoreDescendingCompare {
  bool operator()(const std::pair<uint32_t, float>& l, const std::pair<uint32_t, float>& r) const {
    return l.second > r.second;
  }
};

/**************************************************************************************************************************************************************
 * ResultCompare
 *
 **************************************************************************************************************************************************************/
struct ResultCompare {
  // Only compare the document score, don't care about order of same scoring documents.
  bool operator()(const Result& l, const Result& r) const {
    return l.first > r.first;
  }
};


/**************************************************************************************************************************************************************
 * ResultCompare2
 *
 **************************************************************************************************************************************************************/
struct ResultCompare2 {
  // Only compare the document score, don't care about order of same scoring documents.
  bool operator()(const Result_Wei_2012& l, const Result_Wei_2012& r) const {
    return l.first.totalScore > r.first.totalScore;
  }
};



/**************************************************************************************************************************************************************
 * ListLayerMaxScoreCompare
 *
 * Compares the max document scores of list layers, used to sort list layers by order of importance (the highest scoring layers first).
 **************************************************************************************************************************************************************/
struct ListLayerMaxScoreCompare {
  bool operator()(const ListData* l, const ListData* r) const {
    return l->score_threshold() > r->score_threshold();
  }
};

/**************************************************************************************************************************************************************
 * ListDocIdCompare
 *
 **************************************************************************************************************************************************************/
struct ListDocIdCompare {
  bool operator()(const std::pair<uint32_t, int>& l, const std::pair<uint32_t, int>& r) const {
    return l.first < r.first;
  }
};

/**************************************************************************************************************************************************************
 * ListMaxDocIdCompare
 *
 **************************************************************************************************************************************************************/
struct ListMaxDocIdCompare {
  bool operator()(const std::pair<uint32_t, int>& l, const std::pair<uint32_t, int>& r) const {
    return l.first > r.first;
  }
};

#endif /* QUERY_PROCESSOR_H_ */
